'''
	词法分析器
'''

from enums import Enums;
from error.error import lexer_error;
from error.LexerError import LexerError;

# raise LexerError('ok','jjj');
# exit();


class Token:
	def __init__(self,type,value,lineNumber,columnNumber):
		self.tokenType=type;
		self.value=value;
		#字符所在行号
		self.lineNumber=lineNumber;
		#字符所在列
		self.columnNumber=columnNumber;

	def viewTree(self):
		return {
			'tokenType':self.tokenType,
			'value':self.value,
			'lineNumber':self.lineNumber,
			'columnNumber':self.columnNumber,
		};


class Lexer:

	def __init__(self,sourceCode):
		self.sourceCode=sourceCode;
		self.poistion=0;
		#当前字符
		self.current_char = self.sourceCode[self.poistion];
		self.lineCount=0; # 字符所在行号

		self.tokens=[];
		self.current_keyword='';

		#构建保留关键字
		self.RESERVED_KEYWORDS = self.build_reserved_keywords();

		self.line=1; #行坐标
		self.column=1; #列坐标


	def lexing(self):
		i=0;
		while 1:
			result=self.nextToken();
			self.tokens.append(result)
			i+=1;
			if result.tokenType=='EOF':
				break;
		return self.tokens;


	def nextToken(self):

		lineCount=self.lineCount;
		while self.current_char != None:
			if self.current_char.isspace() or self.current_char=="\n" or self.current_char=="\t":
				self.skip_whitespace()
				continue;
			if self.current_char.isdigit():
				# 数字
				return self.number();

			# 如果当前字符为斜杠注释起始标记
			if self.current_char == '/' and self.peek() == '/':
				self.advance()  # 跳过当前字符
				self.skip_slash_comment()  # 跳过斜杠注释内容
				continue  # 继续获取下一记号

			# ============= start 算术运算符 =========== #

			if self.current_char=='+' and self.peek()!='=':
				self.advance();
				return Token(Enums.PLUS.value,'+',self.line,self.column);
			if self.current_char=='-' and self.peek()!='=':
				self.advance();
				return Token(Enums.MINUS.value,'-',self.line,self.column);
			if self.current_char=='*' and self.peek()!='=':
				self.advance();
				return Token(Enums.MUL.value,'*',self.line,self.column);
			if self.current_char=='/' and self.peek()!='=':
				self.advance();
				return Token(Enums.DIV.value,'/',self.line,self.column);

			# ============= end 算术运算符 =========== #

			# ============= start 双引号，单引号 =========== #

			if self.current_char=='"' :
				return self.getString('"');
			if self.current_char=='\'':
				return self.getString('\'');

			# ============= end 双引号，单引号 =========== #

			if self.current_char=='(':
				self.advance();
				return Token(Enums.LPAREN.value,'(',self.line,self.column);
			if self.current_char==')':
				self.advance();
				return Token(Enums.RPAREN.value,')',self.line,self.column);
			if self.current_char==';':
				self.advance();
				return Token(Enums.SEMI.value,';',self.line,self.column);
			if self.current_char==',':
				self.advance();
				return Token(Enums.COMMA.value,',',self.line,self.column);
			if self.current_char=='{':
				self.advance();
				return Token(Enums.LEFT_RPAREN.value,'{',self.line,self.column);
			if self.current_char=='}':
				self.advance();
				return Token(Enums.RIGHT_RPAREN.value,'}',self.line,self.column);

			# ============= start 赋值运算符 =========== #
			if self.current_char=='=' and self.peek()!='=':
				self.advance();
				return Token(Enums.ASSIGN.value,'=',self.line,self.column);
			if self.current_char=='+' and self.peek()=='=':
				self.advance();
				self.advance();
				return Token(Enums.PLUS_ASSIGN.value,'+=',self.line,self.column);
			if self.current_char=='-' and self.peek()=='=':
				self.advance();
				self.advance();
				return Token(Enums.MINUS_ASSIGN.value,'-=',self.line,self.column);
			if self.current_char=='*' and self.peek()=='=':
				self.advance();
				self.advance();
				return Token(Enums.MUL_ASSIGN.value,'*=',self.line,self.column);
			if self.current_char=='/' and self.peek()=='=':
				self.advance();
				self.advance();
				return Token(Enums.DIV_ASSIGN.value,'/=',self.line,self.column);
			# ============= end 赋值运算符 =========== #

			# ============= start 比较运算符 =========== #
			if self.current_char=='=' and self.peek()=='=':
				self.advance();
				self.advance();
				return Token(Enums.EQUAL.value,'==',self.line,self.column);
			if self.current_char=='!' and self.peek()=='=':
				self.advance();
				self.advance();
				return Token(Enums.NOTEQUAL.value,'!=',self.line,self.column);
			if self.current_char=='>':
				if self.current_char=='>' and self.peek()=='=':
					self.advance();
					self.advance();
					return Token(Enums.GREATER_THAN_EQUAL.value,'>=',self.line,self.column);
				else:
					self.advance();
					return Token(Enums.GREATER_THAN.value,'>',self.line,self.column);
			if self.current_char=='<':
				if self.current_char=='<' and self.peek()=='=':
					self.advance();
					self.advance();
					return Token(Enums.LESS_THAN_EQUAL.value,'<=',self.line,self.column);
				else:
					self.advance();
					return Token(Enums.LESS_THAN.value,'<',self.line,self.column);
			# ============= end 比较运算符 =========== #

			if self.current_char.isalpha() or self.current_char=='_':
				# 变量和关键字
				return self.variable();
			lexer_error('','警告：输入内容有误！');
		else:
			return Token(Enums.EOF.value,'EOF',self.line,self.column);


	#获取下一个字符
	def advance(self):
		if self.current_char == '\n':
			self.line += 1
			self.column = 0

		self.poistion+=1;
		if self.poistion>=len(self.sourceCode):
			self.current_char=None;
		else:
			self.current_char=self.sourceCode[self.poistion];
			self.column += 1

	def number(self):
		number='';
		while self.current_char!=None and self.current_char.isdigit():
			number+=self.current_char;
			self.advance();
			if self.current_char=='.':
				number+=self.current_char;
				self.advance();
				while self.current_char!=None and self.current_char.isdigit():
					number+=self.current_char;
					self.advance();
				return Token(Enums.FLOAT.value,float(number),self.line,self.column);
		return Token(Enums.INTEGER.value,int(number),self.line,self.column);

	def skip_whitespace(self):
		while self.current_char is not None and self.current_char.isspace():
			if self.current_char=="\n" or self.current_char=="\t":
				self.lineCount+=1;
			self.advance();

	def variable(self):
		result='';
		while (self.current_char != None and self.current_char.isalnum()) or (self.current_char != None and self.current_char=='_'):
			result+=self.current_char;
			self.advance();
		#获取关键字
		keywordsType = self.RESERVED_KEYWORDS.get(result.upper());
		token=Token(Enums.VARIABLE.value,result,self.line,self.column);
		if keywordsType is not None:
			if result.upper()==Enums.TRUE.value:
				token=Token(Enums.BOOLEAN.value,result,self.line,self.column);
			elif result.upper()==Enums.FALSE.value:
				token=Token(Enums.BOOLEAN.value,result,self.line,self.column);
			else:
				token=Token(keywordsType,result,self.line,self.column);
		return token;

	def peek(self):
		pos=self.poistion+1;
		if pos>=len(self.sourceCode):
			return None;
		else:
			return self.sourceCode[pos];

	# 获取上一个字符
	def prev_char(self):
		return self.sourceCode[self.poistion-1];

	# 获取字符串
	def getString(self,char):
		result='';
		self.advance();
		while self.current_char!=None:
			if self.current_char==char:
				break;
			result+=self.current_char;
			self.advance();
		# 跳过引号
		self.advance();
		return Token(Enums.STRING.value,result,self.line,self.column);

	# 获取字符串路径
	def getStringPath(self):
		result='';
		while self.current_char!=None:
			if self.current_char==';':
				break;
			result+=self.current_char;
			self.advance();
		return Token(Enums.STRING.value,result,self.line,self.column);

	# 添加跳过斜杠注释内容到的方法
	def skip_slash_comment(self):
		# 如果当前字符不是注释结束符号
		while self.current_char != '\n':
			self.advance()  # 提取下一个字符
		self.advance()  # 提取下一个字符（跳过注释结束符号）

	#保留关键字
	def build_reserved_keywords(self):
		keywords_list = list(Enums)
		start_index = keywords_list.index(Enums.AND)
		end_index = keywords_list.index(Enums.EOF)
		reserved_keywords = {}
		for token_type in keywords_list[start_index:end_index + 1]:
			reserved_keywords[token_type.value]=token_type.value;
		return reserved_keywords

	def error(self, str):
		raise Error(str)